#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<syslog.h>
#include<signal.h>
#include<errno.h>
#include<string.h>

const char* target_file_path="/home/littlelin/Project/Chat02/build/Server/app";
const char* target_file="app";

#define handle_error(cmd,result)\
    if(result<0)\
        {\
            perror(cmd);\
            exit(EXIT_FAILURE);\
        };

pid_t pid;
int is_shutdown=0;

void signal_handler(int signum){
    switch (signum)
    {
    case SIGHUP:
        syslog(LOG_WARNING,"收到SIGHUP信号...");
        break;
    case SIGTERM:
        syslog(LOG_NOTICE,"接收到终止信号，准备退出守护进程...");
        syslog(LOG_NOTICE,"向子进程发送SIGTERM信号...");
        is_shutdown=1;
        kill(pid,SIGTERM);
        waitpid(pid,NULL,0);
        break;
    default:
        syslog(LOG_INFO,"收到其他信号");
        break;
    }
}

void deamonize(){
    int temp;
    
    pid=fork();
    handle_error("fork",pid);

    if(pid>0){
        exit(0);
    }
    temp=setsid();
    handle_error("setsid",temp);

    
    signal(SIGHUP,signal_handler);
    signal(SIGTERM,signal_handler);


    pid =fork();
    handle_error("fork",pid);
    if(pid>0)exit(0);

    temp=chdir("/");
    handle_error("chdir",temp);

    umask(0);

    for(int x=0;x<sysconf(_SC_OPEN_MAX);x++){
        close(x);
    }

    openlog("this is our deamonize process: ",LOG_PID,LOG_DAEMON);
}

int main(){
    deamonize();
    while(1){
        pid=fork();
        if(pid>0){
            syslog(LOG_INFO,"守护进程正在监听服务端进程...");
            waitpid(-1,NULL,0);
            if(is_shutdown){
                syslog(LOG_NOTICE,"子进程已被回收，即将关闭syslog连接，守护进程退出");
                closelog();
                exit(0);
            }
        }
        else if(pid==0){
            syslog(LOG_INFO,"子进程fork成功");
            syslog(LOG_INFO,"启动服务端进程");

            char *path=target_file_path;
            char *argv[]={target_file,NULL};
            errno=0;
            if(execve(path,argv,NULL)<0){
                syslog(LOG_ERR,"服务端进程启动失败：%s",strerror(errno));
                exit(1);
            }
        }
        else{
            syslog(LOG_ERR,"子进程fork失败");
        }
    }
}
